﻿using Microsoft.TeamFoundation.VersionControl.Client;
using System;
using System.Collections.Generic;
using System.DirectoryServices.AccountManagement;
using System.Linq;
using System.Text;

namespace WorkItemAssociationPolicy
{
    [Serializable]
    public class WorkItemAssociationPolicy : PolicyBase
    {
        #region properties
        /// <summary>
        /// description of this policy
        /// </summary>
        public override string Description
        {
            get
            {
                return "Require check-in to be associated with a single, in-progress task that is assigned to you.";
            }
        }

        /// <summary>
        /// This string is the type of our policy.  It will be displayed to the user in a list
        /// of all installed policy types when they are creating a new policy. 
        /// </summary>
        public override string Type
        {
            get
            {
                return "Work Item Association Policy 1.0";
            }
        }

        /// <summary>
        /// This string is a description of the type of our policy.  It will be displayed to the
        /// user when they select our policy type in the list of policies installed on the system
        /// as mentioned above.
        /// </summary>
        public override string TypeDescription
        {
            get
            {
                return "This policy will require a changeset to be associated with a single, in-progress task that is assigned to you.";
            }
        }

        /// <summary>
        /// the installation instructions for distributing this policy using TFS power tools.
        /// </summary>
        public override string InstallationInstructions
        {
            get
            {
                return "To install the correct policy, please go to the [foo] Team Project, right click on Team Members, select Personal Settings..., ensure that the Install downloaded custom controls checkbox is checked, but Verify strong names is not, and click Download Now.  Then restart Visual Studio.";
            }
        }

        #endregion

        #region methods

        /// <summary>
        /// This method is invoked by the policy framework when the user creates a new checkin
        /// policy or edits an existing checkin policy.  We can use this as an opportunity to
        /// display UI specific to this policy type allowing the user to change the parameters
        /// of the policy.
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public override bool Edit(IPolicyEditArgs args)
        {
            // no configuration to save
            return true;
        }

        /// <summary>
        /// This method performs the actual evaluation.  It is called by the policy framework at various points in time
        /// when policy should be evaluated.
        /// </summary>
        /// <returns>prohibited checkins</returns>
        public override PolicyFailure[] Evaluate()
        {
            List<PolicyFailure> PolicyFailures = new List<PolicyFailure>();

            if (PendingCheckin.WorkItems.CheckedWorkItems.Length == 0)
            {
                PolicyFailures.Add(new PolicyFailure("You must associate this check-in with a single in-progress task that is assigned to you.", this));
            } 
            else if (PendingCheckin.WorkItems.CheckedWorkItems.Length == 1)
            {
                if (PendingCheckin.WorkItems.CheckedWorkItems[0].WorkItem.Type.Name != "Task")
                {
                    PolicyFailures.Add(new PolicyFailure(
                        string.Format("You must associate this check-in with a Task, not {0}.",
                        PendingCheckin.WorkItems.CheckedWorkItems[0].WorkItem.Type.Name), this));
                }
                if (PendingCheckin.WorkItems.CheckedWorkItems[0].WorkItem.State != "In Progress")
                {
                    PolicyFailures.Add(new PolicyFailure(
                        string.Format("You must associate this check-in with a work item with status set to \"In Progress\", not \"{0}\".",
                        PendingCheckin.WorkItems.CheckedWorkItems[0].WorkItem.State), this));
                }
                if (!PendingCheckin.WorkItems.CheckedWorkItems[0].WorkItem.Fields["System.AssignedTo"].Value.ToString().StartsWith(UserPrincipal.Current.DisplayName, StringComparison.InvariantCultureIgnoreCase))
                {
                    PolicyFailures.Add(new PolicyFailure(
                        string.Format("You must associate this check-in with a work item assigned to you, not {0}.",
                        PendingCheckin.WorkItems.CheckedWorkItems[0].WorkItem.Fields["System.AssignedTo"].Value.ToString()), this));
                }
            }
            else if (PendingCheckin.WorkItems.CheckedWorkItems.Length > 1)
            {
                PolicyFailures.Add(new PolicyFailure("You must associate this check-in with a single work item.", this));
            }

            return PolicyFailures.ToArray();
        }

        # endregion
    }
}
